package com.qingcheng.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.qingcheng.dao.*;
import com.qingcheng.entity.PageResult;
import com.qingcheng.pojo.goods.Sku;
import com.qingcheng.pojo.order.*;
import com.qingcheng.service.goods.SkuService;
import com.qingcheng.service.order.CartService;
import com.qingcheng.service.order.OrderService;
import com.qingcheng.service.order.WxPayService;
import com.qingcheng.utils.IdWorker;
import org.apache.zookeeper.KeeperException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;


import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service(interfaceClass = OrderService.class)
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    /**
     * 返回全部记录
     *
     * @return
     */
    public List<Order> findAll() {
        return orderMapper.selectAll();
    }

    /**
     * 分页查询
     *
     * @param page 页码
     * @param size 每页记录数
     * @return 分页结果
     */
    public PageResult<Order> findPage(int page, int size) {
        PageHelper.startPage(page, size);
        Page<Order> orders = (Page<Order>) orderMapper.selectAll();
        return new PageResult<Order>(orders.getTotal(), orders.getResult());
    }

    /**
     * 条件查询
     *
     * @param searchMap 查询条件
     * @return
     */
    public List<Order> findList(Map<String, Object> searchMap) {
        Example example = createExample(searchMap);
        //筛选选中的订单中未发货的订单
        if (searchMap.get("ids") != null) {
            Example.Criteria criteria = example.createCriteria();
            criteria.andIn("id", Arrays.asList((String[]) searchMap.get("ids")));
        }
        return orderMapper.selectByExample(example);
    }

    /**
     * 分页+条件查询
     *
     * @param searchMap
     * @param page
     * @param size
     * @return
     */
    public PageResult<Order> findPage(Map<String, Object> searchMap, int page, int size) {
        PageHelper.startPage(page, size);
        Example example = createExample(searchMap);
        //根据更新时间倒序
        example.setOrderByClause("update_time desc");
        Page<Order> orders = (Page<Order>) orderMapper.selectByExample(example);
        return new PageResult<Order>(orders.getTotal(), orders.getResult());
    }

    /**
     * 根据Id查询
     *
     * @param id
     * @return
     */
    public Order findById(String id) {
        return orderMapper.selectByPrimaryKey(id);
    }

    @Autowired
    private CartService cartService;
    @Reference
    private SkuService skuService;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private OrderLogMapper orderLogMapper;

    /**
     * 新增
     *
     * @param order
     */
    @Transactional
    public Map<String, Object> add(Order order) {
        //刷新购物车
        List<Map<String, Object>> cartList = cartService.findNewCartList(order.getUsername());
        //获取选中的购物车
        List<OrderItem> orderItemList = cartList.stream().filter(cart -> (boolean) cart.get("checked"))
                .map(cart -> (OrderItem) cart.get("item"))
                .collect(Collectors.toList());
        //扣减库存
        boolean flag = skuService.deductionStock(orderItemList);
        if (!flag) {
            throw new RuntimeException("库存扣减失败!");
        }
        try {
            //保存订单主表
            order.setId(idWorker.nextId() + "");
            IntStream numStream = orderItemList.stream().mapToInt(OrderItem::getNum);
            IntStream moneyStream = orderItemList.stream().mapToInt(OrderItem::getMoney);
            int totalNum = numStream.sum();//总数量
            int totalMoney = moneyStream.sum();//订单总金额
            int preMoney = cartService.preferential(order.getUsername()); //计算优惠金额
            order.setTotalNum(totalNum);
            order.setTotalMoney(totalMoney);
            order.setPreMoney(preMoney);//优惠金额
            order.setPayMoney(totalMoney - preMoney);//支付金额=总金额+优惠金额
            order.setCreateTime(new Date());//订单创建日期
            order.setOrderStatus("0"); // 订单状态
            order.setPayStatus("0"); // 支付状态：未支付
            order.setConsignStatus("0"); //发货状态：未发货
            orderMapper.insert(order);

            //保存订单明细表
            double proportion = (double) order.getPayMoney() / totalMoney; //打折比例
            for (OrderItem orderItem : orderItemList) {
                orderItem.setOrderId(order.getId());//订单主表ID
                orderItem.setId(idWorker.nextId() + "");
                orderItem.setPayMoney((int) (orderItem.getMoney() *
                        proportion));//支付金额
                orderItemMapper.insert(orderItem);
            }
        } catch (Exception e) {
            //发送回滚消息
            rabbitTemplate.convertAndSend("", "queue.skuback", JSON.toJSONString(orderItemList));
            throw new RuntimeException("创建订单失败!");
        }

        //清除购物车
        cartService.deleteCheckedCart(order.getUsername());
        Map map = new HashMap();
        map.put("ordersn", order.getId());
        map.put("money", order.getPayMoney());
        return map;
    }
    @Autowired
    private WxPayService wxPayService;

    /**
     * 关闭订单
     * @param order
     * @return
     */
    @Transactional
    public void close(Order order) {
        //调用微信支付关闭订单
        Boolean aBoolean = wxPayService.closeNative(order.getId());
        if(aBoolean){
             Boolean aNative = wxPayService.findNative(order.getId());
             //修改订单表的订单状态
              if (aNative==true) {
                  order.setOrderStatus(order.getOrderStatus()+1); // 订单状态
                  order.setPayStatus("1"); // 支付状态：未支付
              }else {
                 order.setOrderStatus("0");
                 order.setPayStatus("0");
                 }
        }else {
            throw new Error();
        }
        //记录订单日志
        OrderLog orderLog=new OrderLog();
        orderLog.setId(idWorker.nextId()+"");
        orderLog.setOrderId(order.getId());
        orderLog.setOrderStatus(order.getOrderStatus());
        orderLog.setPayStatus(order.getPayStatus());
        orderLog.setOperateTime(new Date());
        orderLog.setOperater("system");
        orderLog.setRemarks(order.getTransactionId());
        orderLogMapper.insert(orderLog);


        //恢复商品表库存
        //下次

    }

    /**
     * 修改
     *
     * @param order
     */
    public void update(Order order) {
        orderMapper.updateByPrimaryKeySelective(order);
    }

    /**
     * 删除
     *
     * @param id
     */
    public void delete(String id) {
        orderMapper.deleteByPrimaryKey(id);
    }

    /**
     * 修改订单状态
     *
     * @param orderId       订单号
     * @param transactionId 流水号
     */
    @Override
    @Transactional
    public void updatePayStatus(String orderId, String transactionId) {

        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (order != null && "0".equals(order.getPayStatus())) {
            //修改订单状态信息
            order.setPayStatus("1");
            order.setOrderStatus("1");
            order.setUpdateTime(new Date());
            order.setPayTime(new Date());
            order.setTransactionId(transactionId);//微信返回的交易流水号
            orderMapper.updateByPrimaryKeySelective(order);
            //记录订单变动日志
            OrderLog orderLog = new OrderLog();
            orderLog.setId(idWorker.nextId() + "");
            orderLog.setOperater("system");// 系统
            orderLog.setOperateTime(new Date());//当前日期
            orderLog.setOrderStatus("1");
            orderLog.setPayStatus("1");
            orderLog.setRemarks("支付流水号" + transactionId);
            orderLog.setOrderId(orderId);
            orderLogMapper.insert(orderLog);
        }
    }

    /**
     * 查询订单和该订单的订单详情
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderOrderItem findOrderAndOrderItems(String orderId) {
        //根据订单id查询order
        Order order = orderMapper.selectByPrimaryKey(orderId);
        //根据orderId查询该id所有的详情
        Example example = new Example(OrderItem.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("orderId", orderId);
        List<OrderItem> orderItemList = orderItemMapper.selectByExample(example);

        List<Sku> skuList = new ArrayList<>();
        //根据skuId查询sku
        for (OrderItem orderItem : orderItemList) {
            String skuId = orderItem.getSkuId(); //获取skuId
            Sku sku = skuService.findById(skuId);//sku
            skuList.add(sku); //加入list中
        }
        //封装入OrderOrderItem联合实体类中
        OrderOrderItem orderOrderItem = new OrderOrderItem();
        orderOrderItem.setOrder(order);
        orderOrderItem.setOrderItemList(orderItemList);
        orderOrderItem.setSkuList(skuList);
        return orderOrderItem;
    }

    /***
     * 批量发货
     * @param orderList
     */
    @Override
    @Transactional
    public void batchSend(List<Order> orderList) {
        for (Order order : orderList) {
            //判断运单号和物流公司是否为空
            if (order.getShippingCode() == null || order.getShippingName() == null) {
                throw new RuntimeException("未填写快递公司或者运单号!");
            }
            //修改订单表
            order.setConsignStatus("1"); //已发货
            order.setConsignTime(new Date()); //发货时间
            order.setOrderStatus("2"); //订单状态 已发货
            orderMapper.updateByPrimaryKeySelective(order);
            //添加日志信息
            OrderLog orderLog = new OrderLog();
            orderLog.setId(idWorker.nextId() + "");
            orderLog.setOperater("system");// 系统
            orderLog.setOperateTime(new Date());//当前日期
            orderLog.setOrderStatus("2");
            orderLog.setPayStatus("1");
            orderLog.setRemarks("支付流水号" + order.getTransactionId());
            orderLog.setOrderId(order.getId());
            orderLogMapper.insert(orderLog);
        }
    }

    @Autowired
    private OrderConfigMapper orderConfigMapper;

    /***
     * 超时订单处理
     */
    @Override
    @Transactional
    public void orderTimeOutLogic() {
        //查询超时订单处理详情
        List<OrderConfig> orderConfigList = orderConfigMapper.selectAll();
        //因为就一条数据,取index=0即可
        OrderConfig orderConfig = orderConfigList.get(0);
        //订单创建时间+订单超时时间<当前时间的话,就说明订单超时,也就是订单创建时间<当前时间-订单超时时间
        Integer orderTimeout = orderConfig.getOrderTimeout(); //正常商品订单超时时间(分)
        LocalDateTime localDateTime = LocalDateTime.now().minusMinutes(orderTimeout); //当前时间-订单超时时间
        //查询超时的订单
        Example example = new Example(Order.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andLessThan("createTime", localDateTime);
        criteria.andEqualTo("orderStatus", "0"); //待支付状态
        criteria.andEqualTo("isDelete", "0"); //未删除
        List<Order> orderList = orderMapper.selectByExample(example);
        //更改订单状态 记录订单日志
        OrderLog orderLog = new OrderLog();
        for (Order order : orderList) {
            //更改订单状态
            order.setOrderStatus("4"); //已关闭
            order.setCloseTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
            //记录订单日志
            orderLog.setId(idWorker.nextId() + "");
            orderLog.setOperater("system");// 系统
            orderLog.setOperateTime(new Date());//当前日期
            orderLog.setOrderStatus("4"); //关闭订单
            orderLog.setPayStatus(order.getPayStatus()); //支付状态
            orderLog.setConsignStatus(order.getConsignStatus()); //发货状态
            orderLog.setRemarks("超时订单，系统自动关闭");
            orderLog.setOrderId(order.getId());
            orderLogMapper.insert(orderLog);
        }
    }

    @Autowired
    private PreferentialMapper preferentialMapper;

    /***
     * 合并订单
     * 将“从订单”的金额等信息合并到“主订单”，“从订单”的订单明细也归属于主订单
     * 当两个订单不一致时，合并后的订单信息（如：支付方式、配送方式、活动优惠等）以主订单为准。
     * @param orderId1
     * @param orderId2
     */
    @Override
    @Transactional
    public void combineOrders(String orderId1, String orderId2) {
        //1合并订单
        Order order1 = orderMapper.selectByPrimaryKey(orderId1);
        Order order2 = orderMapper.selectByPrimaryKey(orderId2);
        order1.setTotalNum(order1.getTotalNum() + order2.getTotalNum()); //总数量
        order1.setTotalMoney(order1.getTotalMoney() + order2.getTotalMoney()); //总金额
        //重新计算优惠金额
        Integer preMoney = 0;
        Example example = new Example(Preferential.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andLessThanOrEqualTo("buyMoney", order1.getTotalMoney()); //商品金额要大于等于(满多少钱才能优惠的金额) 不然没法优惠
        example.setOrderByClause("buy_money desc"); //倒序排序
        List<Preferential> preferentialList = preferentialMapper.selectByExample(example);
        if (preferentialList.size() > 0) {
            //取第一个元素,最大的优惠
            Preferential preferential = preferentialList.get(0);
            if ("1".equals(preferential.getType())) {  //不翻倍
                preMoney = preferential.getPreMoney();
            } else {
                //翻倍
                int multiple = order1.getTotalMoney() / preferential.getBuyMoney(); //倍数
                preMoney = preferential.getPreMoney() * multiple;
            }
        }
        order1.setPreMoney(preMoney); //优惠金额
        order1.setPayMoney(order1.getTotalMoney() - order1.getPreMoney()); //实际支付金额
        //2将订单明细归属主订单
        Example example1 = new Example(OrderItem.class);
        Example.Criteria criteria1 = example1.createCriteria();
        criteria1.andEqualTo("orderId", orderId2);
        List<OrderItem> orderItemList = orderItemMapper.selectByExample(example); //从订单的订单明细
        for (OrderItem orderItem : orderItemList) {
            //把orderId设置为主订单的id
            orderItem.setOrderId(orderId1);
            orderItemMapper.updateByPrimaryKeySelective(orderItem);
        }
        //3把从订单逻辑删除
        order2.setIsDelete("1");
        orderMapper.updateByPrimaryKeySelective(order2);
    }

    /***
     * 拆分订单
     * @param splitList
     * @param orderId
     */
    @Override
    @Transactional
    public void splitOrder(String orderId, List<Map<Integer, Integer>> splitList) {
        Order order = orderMapper.selectByPrimaryKey(orderId);
        Example example = new Example(OrderItem.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("orderId",order.getId());
        //获得订单详细列表
        List<OrderItem> orderItemList = orderItemMapper.selectByExample(example);
        Integer num = 0; //拆分数量总计
        for (Map<Integer, Integer> map : splitList) {
            for (OrderItem orderItem : orderItemList) {
                if((map.get("id")+"").equals(orderItem.getId())) { //找到相同id的订单详情表
                    //判断数量是否符合要求
                    if(map.get("num")>orderItem.getNum()) {
                        throw new RuntimeException("拆分数量不符合要求!");
                    }
                    num += map.get("num");
                    break;
                }else {
                    throw new RuntimeException("该订单有误!");
                }
            }
        }
        //拆分订单
        //新增一个订单
        Order newOrder = new Order();
        newOrder.setId(idWorker.nextId()+"");
        newOrder.setTotalNum(num);
        newOrder.setTotalMoney(order.getTotalMoney());
        newOrder.setPreMoney(order.getPreMoney());//优惠金额
        newOrder.setPayMoney(order.getPayMoney());
        newOrder.setCreateTime(new Date());//订单创建日期
        newOrder.setOrderStatus(order.getOrderStatus()); // 订单状态
        newOrder.setPayStatus(order.getPayStatus()); // 支付状态：未支付
        newOrder.setConsignStatus(order.getConsignStatus()); //发货状态：未发货
        orderMapper.insert(newOrder);
        //修改要拆封的订单
        order.setTotalNum(order.getTotalNum()-num);
        orderMapper.updateByPrimaryKeySelective(order);
    }


    /**
     * 构建查询条件
     *
     * @param searchMap
     * @return
     */
    private Example createExample(Map<String, Object> searchMap) {
        Example example = new Example(Order.class);
        Example.Criteria criteria = example.createCriteria();
        if (searchMap != null) {
            // 订单id
            if (searchMap.get("id") != null && !"".equals(searchMap.get("id"))) {
                criteria.andLike("id", "%" + searchMap.get("id") + "%");
            }
            // 支付类型，1、在线支付、0 货到付款
            if (searchMap.get("payType") != null && !"".equals(searchMap.get("payType"))) {
                criteria.andLike("payType", "%" + searchMap.get("payType") + "%");
            }
            // 物流名称
            if (searchMap.get("shippingName") != null && !"".equals(searchMap.get("shippingName"))) {
                criteria.andLike("shippingName", "%" + searchMap.get("shippingName") + "%");
            }
            // 物流单号
            if (searchMap.get("shippingCode") != null && !"".equals(searchMap.get("shippingCode"))) {
                criteria.andLike("shippingCode", "%" + searchMap.get("shippingCode") + "%");
            }
            // 用户名称
            if (searchMap.get("username") != null && !"".equals(searchMap.get("username"))) {
                criteria.andLike("username", "%" + searchMap.get("username") + "%");
            }
            // 买家留言
            if (searchMap.get("buyerMessage") != null && !"".equals(searchMap.get("buyerMessage"))) {
                criteria.andLike("buyerMessage", "%" + searchMap.get("buyerMessage") + "%");
            }
            // 是否评价
            if (searchMap.get("buyerRate") != null && !"".equals(searchMap.get("buyerRate"))) {
                criteria.andLike("buyerRate", "%" + searchMap.get("buyerRate") + "%");
            }
            // 收货人
            if (searchMap.get("receiverContact") != null && !"".equals(searchMap.get("receiverContact"))) {
                criteria.andLike("receiverContact", "%" + searchMap.get("receiverContact") + "%");
            }
            // 收货人手机
            if (searchMap.get("receiverMobile") != null && !"".equals(searchMap.get("receiverMobile"))) {
                criteria.andLike("receiverMobile", "%" + searchMap.get("receiverMobile") + "%");
            }
            // 收货人地址
            if (searchMap.get("receiverAddress") != null && !"".equals(searchMap.get("receiverAddress"))) {
                criteria.andLike("receiverAddress", "%" + searchMap.get("receiverAddress") + "%");
            }
            // 订单来源：1:web，2：app，3：微信公众号，4：微信小程序  5 H5手机页面
            if (searchMap.get("sourceType") != null && !"".equals(searchMap.get("sourceType"))) {
                criteria.andLike("sourceType", "%" + searchMap.get("sourceType") + "%");
            }
            // 交易流水号
            if (searchMap.get("transactionId") != null && !"".equals(searchMap.get("transactionId"))) {
                criteria.andLike("transactionId", "%" + searchMap.get("transactionId") + "%");
            }
            // 订单状态
            if (searchMap.get("orderStatus") != null && !"".equals(searchMap.get("orderStatus"))) {
                criteria.andLike("orderStatus", "%" + searchMap.get("orderStatus") + "%");
            }
            // 支付状态
            if (searchMap.get("payStatus") != null && !"".equals(searchMap.get("payStatus"))) {
                criteria.andLike("payStatus", "%" + searchMap.get("payStatus") + "%");
            }
            // 发货状态
            if (searchMap.get("consignStatus") != null && !"".equals(searchMap.get("consignStatus"))) {
                criteria.andLike("consignStatus", "%" + searchMap.get("consignStatus") + "%");
            }
            // 是否删除
            if (searchMap.get("isDelete") != null && !"".equals(searchMap.get("isDelete"))) {
                criteria.andLike("isDelete", "%" + searchMap.get("isDelete") + "%");
            }

            // 数量合计
            if (searchMap.get("totalNum") != null) {
                criteria.andEqualTo("totalNum", searchMap.get("totalNum"));
            }
            // 金额合计
            if (searchMap.get("totalMoney") != null) {
                criteria.andEqualTo("totalMoney", searchMap.get("totalMoney"));
            }
            // 优惠金额
            if (searchMap.get("preMoney") != null) {
                criteria.andEqualTo("preMoney", searchMap.get("preMoney"));
            }
            // 邮费
            if (searchMap.get("postFee") != null) {
                criteria.andEqualTo("postFee", searchMap.get("postFee"));
            }
            // 实付金额
            if (searchMap.get("payMoney") != null) {
                criteria.andEqualTo("payMoney", searchMap.get("payMoney"));
            }

        }
        return example;
    }

}
